package au.com.handsunited.model.validators.entity;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;

import au.com.handsunited.model.Address;
import au.com.handsunited.model.Availability;
import au.com.handsunited.model.BaseEntity;
import au.com.handsunited.model.BaseEntity;
import au.com.handsunited.model.ContactInfo;
import au.com.handsunited.model.validators.address.AddressValidator;
import au.com.handsunited.model.validators.availability.AvailabilityValidator;
import au.com.handsunited.model.validators.contactinfo.ContactInfoValidator;

/**
 * @author arunda
 *
 */
public class BaseEntityValidator implements Validator {


	protected AddressValidator locationValidator;
	protected ContactInfoValidator contactInfoValidator;
	protected AvailabilityValidator availabilityValidator;

	private static Logger logger = LoggerFactory.getLogger(BaseEntityValidator.class);

	public BaseEntityValidator(AddressValidator locationValidator, ContactInfoValidator contactInfoValidator, AvailabilityValidator availabilityValidator) {

		if (contactInfoValidator == null) {
			throw new IllegalArgumentException("The supplied ContactInfoValidator is required and must not be null.");
		}
		if (locationValidator == null) {
			throw new IllegalArgumentException("The supplied AddressValidator is required and must not be null.");
		}
		if (availabilityValidator == null) {
			throw new IllegalArgumentException("The supplied AvailabilityValidator is required and must not be null.");
		}


		if (!contactInfoValidator.supports(ContactInfo.class)) {
			throw new IllegalArgumentException("The supplied ContactInfoValidator must support the validation of ContactInfo instances.");
		}

		if (!locationValidator.supports(Address.class)) {
			throw new IllegalArgumentException("The supplied AddressValidator must support the validation of Address instances.");
		}

		if (!availabilityValidator.supports(Availability.class)) {
			throw new IllegalArgumentException("The supplied AvailabilityValidator must support the validation of Availability instances.");
		}

		this.contactInfoValidator = contactInfoValidator;
		this.locationValidator = locationValidator;
		this.availabilityValidator = availabilityValidator;
	}


	/**
	 * @see org.springframework.validation.Validator#supports(java.lang.Class)
	 */
	@Override
	public boolean supports(Class clazz) {
		return clazz.isAssignableFrom(BaseEntity.class);
	}

	/**
	 * @see org.springframework.validation.Validator#validate(java.lang.Object, org.springframework.validation.Errors)
	 */
	@Override
	public void validate(Object target, Errors errors) {

		BaseEntity entity = (BaseEntity) target;

		try {
			errors.pushNestedPath("contactInfo");
			ValidationUtils.invokeValidator(contactInfoValidator, entity.getContactInfo(), errors);
		} finally {
			errors.popNestedPath();
		}

		try {
			errors.pushNestedPath("location");
			ValidationUtils.invokeValidator(locationValidator, entity.getLocation(), errors);
		} finally {
			errors.popNestedPath();
		}

		try {
			errors.pushNestedPath("availability");
			ValidationUtils.invokeValidator(availabilityValidator, entity.getAvailability(), errors);
		} finally {
			errors.popNestedPath();
		}

	}

}
